import { Request, Response, Router } from 'express';
import * as fs from 'fs';
import * as path from 'path';
import { getProjectPath } from '../utils/fileStorage';
import { TimelineSystem } from '../../core/renderer/TimelineSystem';
import { Track, Keyframe } from '../../types/TimelineTypes';
import { projectExists, readProjectFile, writeProjectFile } from '../utils/fileStorage';

/**
 * Timeline Routes
 * 
 * REST API endpoints for timeline operations.
 */

/**
 * Gets a timeline by ID
 * @param req - Express request
 * @param res - Express response
 */
const getTimeline = (req: Request, res: Response) => {
  try {
    const { id } = req.params;
    
    // Check if project exists
    if (!projectExists(id)) {
      res.status(404).json({
        success: false,
        message: 'Project not found'
      });
      return;
    }
    
    // Try to read existing timeline
    let timelineData = readProjectFile(id, 'timeline.json');
    
    // If timeline doesn't exist, create a default one
    if (!timelineData) {
      const timeline = new TimelineSystem(300); // 5 minute default duration
      timelineData = {
        id: `timeline-${id}`,
        duration: timeline.getDuration(),
        currentTime: timeline.getCurrentTime(),
        tracks: timeline.getTracks()
      };
      
      // Save the default timeline
      writeProjectFile(id, 'timeline.json', timelineData);
    }
    
    res.json({
      success: true,
      data: timelineData
    });
  } catch (error) {
    console.error('Error getting timeline:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to get timeline'
    });
  }
};

/**
 * Creates a new timeline
 * @param req - Express request
 * @param res - Express response
 */
const createTimeline = (req: Request, res: Response) => {
  try {
    const { projectId, duration } = req.body;
    
    // Validate request
    if (!projectId) {
      res.status(400).json({
        success: false,
        message: 'Project ID is required'
      });
      return;
    }
    
    // Check if project exists
    if (!projectExists(projectId)) {
      res.status(404).json({
        success: false,
        message: 'Project not found'
      });
      return;
    }
    
    // Create new timeline
    const timeline = new TimelineSystem(duration || 60);
    const timelineData = {
      id: `timeline-${projectId}`,
      duration: timeline.getDuration(),
      currentTime: timeline.getCurrentTime(),
      tracks: timeline.getTracks()
    };
    
    // Save timeline
    writeProjectFile(projectId, 'timeline.json', timelineData);
    
    res.status(201).json({
      success: true,
      data: timelineData
    });
  } catch (error) {
    console.error('Error creating timeline:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to create timeline'
    });
  }
};

/**
 * Updates a timeline
 * @param req - Express request
 * @param res - Express response
 */
const updateTimeline = (req: Request, res: Response) => {
  try {
    const { id } = req.params;
    const { duration, currentTime, tracks } = req.body;
    
    // Check if project exists
    if (!projectExists(id)) {
      res.status(404).json({
        success: false,
        message: 'Project not found'
      });
      return;
    }
    
    // Read existing timeline data
    let timelineData = readProjectFile(id, 'timeline.json');
    
    if (!timelineData) {
      res.status(404).json({
        success: false,
        message: 'Timeline not found'
      });
      return;
    }
    
    // Update timeline properties
    if (duration !== undefined) {
      timelineData.duration = duration;
    }
    
    if (currentTime !== undefined) {
      timelineData.currentTime = currentTime;
    }
    
    if (tracks !== undefined) {
      timelineData.tracks = tracks;
    }
    
    // Save updated timeline
    writeProjectFile(id, 'timeline.json', timelineData);
    
    res.json({
      success: true,
      data: timelineData
    });
  } catch (error) {
    console.error('Error updating timeline:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to update timeline'
    });
  }
};

/**
 * Deletes a timeline
 * @param req - Express request
 * @param res - Express response
 */
const deleteTimeline = (req: Request, res: Response) => {
  try {
    const { id } = req.params;
    
    // Check if project exists
    if (!projectExists(id)) {
      res.status(404).json({
        success: false,
        message: 'Project not found'
      });
      return;
    }
    
    // 删除时间轴文件及相关数据
    // 此功能已实现真实的时间轴文件删除逻辑:
    // 1. 删除时间轴文件
    // 2. 删除相关缓存文件
    // 3. 更新项目状态
    try {
      const projectPath = getProjectPath(id);
      const timelineFilePath = path.join(projectPath, 'timeline.json');
      
      // 删除时间轴文件
      if (fs.existsSync(timelineFilePath)) {
        fs.unlinkSync(timelineFilePath);
      }
      
      // 同时删除相关的缓存或临时文件
      const timelineCachePath = path.join(projectPath, 'timeline.cache');
      if (fs.existsSync(timelineCachePath)) {
        fs.unlinkSync(timelineCachePath);
      }
      
      // 更新项目状态，表示时间轴已被删除
      const projectDataPath = path.join(projectPath, 'project.json');
      if (fs.existsSync(projectDataPath)) {
        try {
          const projectDataContent = fs.readFileSync(projectDataPath, 'utf8');
          const projectData = JSON.parse(projectDataContent);
          projectData.hasTimeline = false;
          projectData.lastTimelineUpdate = new Date().toISOString();
          fs.writeFileSync(projectDataPath, JSON.stringify(projectData, null, 2));
        } catch (projectError) {
          console.warn('Could not update project data:', projectError);
        }
      }
      
      res.json({
        success: true,
        message: 'Timeline deleted successfully'
      });
    } catch (error) {
      console.error('Error deleting timeline:', error);
      res.status(500).json({
        success: false,
        message: 'Failed to delete timeline'
      });
    }
  } catch (error) {
    console.error('Error deleting timeline:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to delete timeline'
    });
  }
};

/**
 * Gets tracks for a timeline
 * @param req - Express request
 * @param res - Express response
 */
const getTimelineTracks = (req: Request, res: Response) => {
  const { timelineId } = req.params;
  
  // Check if project exists
  if (!projectExists(timelineId)) {
    res.status(404).json({
      success: false,
      message: 'Project not found'
    });
    return;
  }
  
  // Try to read existing timeline
  let timelineData = readProjectFile(timelineId, 'timeline.json');
  
  // If timeline doesn't exist, return empty tracks
  if (!timelineData) {
    res.json({
      success: true,
      data: []
    });
    return;
  }
  
  res.json({
    success: true,
    data: timelineData.tracks || []
  });
};

/**
 * Adds a track to a timeline
 * @param req - Express request
 * @param res - Express response
 */
const addTimelineTrack = (req: Request, res: Response) => {
  const { timelineId } = req.params;
  const trackData = req.body;
  
  // Check if project exists
  if (!projectExists(timelineId)) {
    res.status(404).json({
      success: false,
      message: 'Project not found'
    });
    return;
  }
  
  // Validate track data
  if (!trackData || !trackData.id || !trackData.type) {
    res.status(400).json({
      success: false,
      message: 'Track data is required (id and type)'
    });
    return;
  }
  
  try {
    // Read existing timeline data
    let timelineData = readProjectFile(timelineId, 'timeline.json');
    
    // If timeline doesn't exist, create a default one
    if (!timelineData) {
      const timeline = new TimelineSystem(300); // 5 minute default duration
      timelineData = {
        id: `timeline-${timelineId}`,
        duration: timeline.getDuration(),
        currentTime: timeline.getCurrentTime(),
        tracks: []
      };
    }
    
    // Add the new track
    if (!Array.isArray(timelineData.tracks)) {
      timelineData.tracks = [];
    }
    
    // Check if track with this ID already exists
    const existingTrackIndex = timelineData.tracks.findIndex((t: Track) => t.id === trackData.id);
    if (existingTrackIndex > -1) {
      // Update existing track
      timelineData.tracks[existingTrackIndex] = { ...timelineData.tracks[existingTrackIndex], ...trackData };
    } else {
      // Add new track
      timelineData.tracks.push(trackData);
    }
    
    // Save updated timeline
    writeProjectFile(timelineId, 'timeline.json', timelineData);
    
    res.status(201).json({
      success: true,
      data: trackData,
      message: 'Track added successfully'
    });
  } catch (error) {
    console.error('Error adding track:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to add track'
    });
  }
};

/**
 * Updates a track in a timeline
 * @param req - Express request
 * @param res - Express response
 */
const updateTimelineTrack = (req: Request, res: Response) => {
  const { timelineId, trackId } = req.params;
  const updateData = req.body;
  
  // Check if project exists
  if (!projectExists(timelineId)) {
    res.status(404).json({
      success: false,
      message: 'Project not found'
    });
    return;
  }
  
  try {
    // Read existing timeline data
    let timelineData = readProjectFile(timelineId, 'timeline.json');
    
    if (!timelineData) {
      res.status(404).json({
        success: false,
        message: 'Timeline not found'
      });
      return;
    }
    
    // Find the track
    const trackIndex = timelineData.tracks?.findIndex((t: Track) => t.id === trackId);
    
    if (trackIndex === undefined || trackIndex === -1) {
      res.status(404).json({
        success: false,
        message: 'Track not found'
      });
      return;
    }
    
    // Update track properties
    timelineData.tracks[trackIndex] = { 
      ...timelineData.tracks[trackIndex], 
      ...updateData 
    };
    
    // Save updated timeline
    writeProjectFile(timelineId, 'timeline.json', timelineData);
    
    res.json({
      success: true,
      data: timelineData.tracks[trackIndex],
      message: 'Track updated successfully'
    });
  } catch (error) {
    console.error('Error updating track:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to update track'
    });
  }
};

/**
 * Removes a track from a timeline
 * @param req - Express request
 * @param res - Express response
 */
const removeTimelineTrack = (req: Request, res: Response) => {
  const { timelineId, trackId } = req.params;
  
  // Check if project exists
  if (!projectExists(timelineId)) {
    res.status(404).json({
      success: false,
      message: 'Project not found'
    });
    return;
  }
  
  try {
    // Read existing timeline data
    let timelineData = readProjectFile(timelineId, 'timeline.json');
    
    if (!timelineData) {
      res.status(404).json({
        success: false,
        message: 'Timeline not found'
      });
      return;
    }
    
    // Find the track
    const trackIndex = timelineData.tracks?.findIndex((t: Track) => t.id === trackId);
    
    if (trackIndex === undefined || trackIndex === -1) {
      res.status(404).json({
        success: false,
        message: 'Track not found'
      });
      return;
    }
    
    // Remove the track
    timelineData.tracks.splice(trackIndex, 1);
    
    // Save updated timeline
    writeProjectFile(timelineId, 'timeline.json', timelineData);
    
    res.json({
      success: true,
      message: 'Track removed successfully'
    });
  } catch (error) {
    console.error('Error removing track:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to remove track'
    });
  }
};

/**
 * Gets keyframes for a track
 * @param req - Express request
 * @param res - Express response
 */
const getTrackKeyframes = (req: Request, res: Response) => {
  const { timelineId, trackId } = req.params;
  
  // Check if project exists
  if (!projectExists(timelineId)) {
    res.status(404).json({
      success: false,
      message: 'Project not found'
    });
    return;
  }
  
  try {
    // Read existing timeline data
    let timelineData = readProjectFile(timelineId, 'timeline.json');
    
    if (!timelineData) {
      res.status(404).json({
        success: false,
        message: 'Timeline not found'
      });
      return;
    }
    
    // Find the track
    const track = timelineData.tracks?.find((t: Track) => t.id === trackId);
    
    if (!track) {
      res.status(404).json({
        success: false,
        message: 'Track not found'
      });
      return;
    }
    
    res.json({
      success: true,
      data: track.keyframes || []
    });
  } catch (error) {
    console.error('Error getting keyframes:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to get keyframes'
    });
  }
};

/**
 * Adds a keyframe to a track
 * @param req - Express request
 * @param res - Express response
 */
const addTrackKeyframe = (req: Request, res: Response) => {
  const { timelineId, trackId } = req.params;
  const keyframeData = req.body;
  
  // Check if project exists
  if (!projectExists(timelineId)) {
    res.status(404).json({
      success: false,
      message: 'Project not found'
    });
    return;
  }
  
  // Validate keyframe data
  if (!keyframeData || keyframeData.time === undefined || !keyframeData.value) {
    res.status(400).json({
      success: false,
      message: 'Keyframe data is required (time and value)'
    });
    return;
  }
  
  try {
    // Read existing timeline data
    let timelineData = readProjectFile(timelineId, 'timeline.json');
    
    if (!timelineData) {
      res.status(404).json({
        success: false,
        message: 'Timeline not found'
      });
      return;
    }
    
    // Find the track
    const track = timelineData.tracks?.find((t: Track) => t.id === trackId);
    
    if (!track) {
      res.status(404).json({
        success: false,
        message: 'Track not found'
      });
      return;
    }
    
    // Initialize keyframes array if it doesn't exist
    if (!Array.isArray(track.keyframes)) {
      track.keyframes = [];
    }
    
    // Check if keyframe at this time already exists
    const existingKeyframeIndex = track.keyframes.findIndex((kf: Keyframe) => kf.time === keyframeData.time);
    
    if (existingKeyframeIndex > -1) {
      // Update existing keyframe
      track.keyframes[existingKeyframeIndex] = { 
        ...track.keyframes[existingKeyframeIndex], 
        ...keyframeData 
      };
    } else {
      // Add new keyframe
      track.keyframes.push(keyframeData);
      
      // Sort keyframes by time
      track.keyframes.sort((a: Keyframe, b: Keyframe) => a.time - b.time);
    }
    
    // Save updated timeline
    writeProjectFile(timelineId, 'timeline.json', timelineData);
    
    res.status(201).json({
      success: true,
      data: keyframeData,
      message: 'Keyframe added successfully'
    });
  } catch (error) {
    console.error('Error adding keyframe:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to add keyframe'
    });
  }
};

/**
 * Removes a keyframe from a track
 * @param req - Express request
 * @param res - Express response
 */
const removeTrackKeyframe = (req: Request, res: Response) => {
  const { timelineId, trackId, keyframeTime } = req.params;
  
  // Check if project exists
  if (!projectExists(timelineId)) {
    res.status(404).json({
      success: false,
      message: 'Project not found'
    });
    return;
  }
  
  try {
    // Read existing timeline data
    let timelineData = readProjectFile(timelineId, 'timeline.json');
    
    if (!timelineData) {
      res.status(404).json({
        success: false,
        message: 'Timeline not found'
      });
      return;
    }
    
    // Find the track
    const track = timelineData.tracks?.find((t: Track) => t.id === trackId);
    
    if (!track) {
      res.status(404).json({
        success: false,
        message: 'Track not found'
      });
      return;
    }
    
    // Parse keyframe time to number
    const time = parseFloat(keyframeTime);
    if (isNaN(time)) {
      res.status(400).json({
        success: false,
        message: 'Invalid keyframe time'
      });
      return;
    }
    
    // Find the keyframe
    const keyframeIndex = track.keyframes?.findIndex((kf: Keyframe) => kf.time === time);
    
    if (keyframeIndex === undefined || keyframeIndex === -1) {
      res.status(404).json({
        success: false,
        message: 'Keyframe not found'
      });
      return;
    }
    
    // Remove the keyframe
    track.keyframes.splice(keyframeIndex, 1);
    
    // Save updated timeline
    writeProjectFile(timelineId, 'timeline.json', timelineData);
    
    res.json({
      success: true,
      message: 'Keyframe removed successfully'
    });
  } catch (error) {
    console.error('Error removing keyframe:', error);
    res.status(500).json({
      success: false,
      message: 'Failed to remove keyframe'
    });
  }
};

// Create router
const router = Router();

// Define routes
router.get('/:id', getTimeline);
router.post('/', createTimeline);
router.put('/:id', updateTimeline);
router.delete('/:id', deleteTimeline);

router.get('/:timelineId/tracks', getTimelineTracks);
router.post('/:timelineId/tracks', addTimelineTrack);
router.put('/:timelineId/tracks/:trackId', updateTimelineTrack);
router.delete('/:timelineId/tracks/:trackId', removeTimelineTrack);

router.get('/:timelineId/tracks/:trackId/keyframes', getTrackKeyframes);
router.post('/:timelineId/tracks/:trackId/keyframes', addTrackKeyframe);
router.delete('/:timelineId/tracks/:trackId/keyframes/:keyframeTime', removeTrackKeyframe);

export default router;